﻿using System;
using System.ComponentModel;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using Ext.Net;
using Ext.Net.Utilities;

namespace KamLib.Controls
{
    public enum ColumnKind { None, Normal, Main, Secondary, Utility }
    public enum ColumnBorderKind { None = 0, Normal, Bold }

    public interface IRecordFieldInfo
    {
        RecordFieldType FieldType { get; }
    }


    public interface IColumnEditorFactory
    {
        Field NewEditor();
    }

    public interface IColumnFilterFactory
    {
        bool Filterable { get; }
        GridFilter NewFilter();
    }

    #region Base

    public class Column : global::Ext.Net.Column, IColumnEditorFactory, IColumnFilterFactory
    {
        [DefaultValue(true)]
        [NotifyParentProperty(true)]
        public virtual bool AllowBlank { get { return _allowBlank; } set { _allowBlank = value; } }
        private bool _allowBlank = true;

        [DefaultValue(ColumnBorderKind.None)]
        [NotifyParentProperty(true)]
        public virtual ColumnBorderKind BorderRight { get; set; }

        [DefaultValue(false)]
        [NotifyParentProperty(true)]
        public virtual bool Expanded { get; set; }

        private bool _Filterable = true;
        [NotifyParentProperty(true)]
        public bool Filterable { get { return _Filterable; } set { _Filterable = value; } }

        [NotifyParentProperty(true)]
        public virtual string FilterName { get; set; }

        [NotifyParentProperty(true)]
        public virtual string FilterLabelField { get; set; }

        [NotifyParentProperty(true)]
        public virtual string FilterStoreID { get; set; }

        [DefaultValue(false)]
        [NotifyParentProperty(true)]
        public virtual bool IsKey { get; set; }

        [NotifyParentProperty(true)]
        public string LookupStoreClientID { get; set; }
        [NotifyParentProperty(true)]
        public string LookupField { get; set; }


        [DefaultValue(null)]
        [NotifyParentProperty(true)]
        [Description("Property name of value: value.Prop1[1]")]
        public virtual string GetValue { get; set; }

        [DefaultValue(false)]
        [NotifyParentProperty(true)]
        public virtual bool IsArray { get; set; }

        [DefaultValue(ColumnKind.Normal)]
        [NotifyParentProperty(true)]
        public virtual ColumnKind Kind { get { return _kind; } set { _kind = value; } }
        private ColumnKind _kind = ColumnKind.Normal;

        protected LogicLink _link;
        [NotifyParentProperty(true)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public LogicLink Link { get { return _link ?? (_link = new LogicLink()); } }

        [NotifyParentProperty(true)]
        public virtual string Name { get { return DataIndex; } set { ColumnID = DataIndex = value; } }

        [DefaultValue(false)]
        [NotifyParentProperty(true)]
        public virtual bool ShowErrorIcon { get; set; }

        [DefaultValue(false)]
        [NotifyParentProperty(true)]
        public virtual bool ShowOkIcon { get; set; }


        public virtual GridFilter NewFilter()
        {
            //if (FilterStoreID.isnull()) FilterStoreID = LookupStoreClientID.TrimStart(false, "Refs_");
            if (FilterLabelField.isnull()) FilterLabelField = LookupField;
            return Filterable
                ? FilterStoreID.isnull() && LookupStoreClientID.isnull()
                    ? NewSpecFilter()
                    : null
                    //: new ListFilter { DataIndex = FilterName ?? DataIndex, LabelField = FilterLabelField.IfNull("n") }.With(a =>
                    //{
                    //    if (FilterStoreID.isnull())
                    //        a.StoreClientID = LookupStoreClientID;
                    //    else
                    //        a.StoreID = FilterStoreID;
                    //})
                : null;
        }

        public virtual GridFilter NewSpecFilter()
        {
            return new StringFilter { DataIndex = FilterName ?? DataIndex };
        }


        #region Render

        [NotifyParentProperty(true)]
        public string RenderHandler { get { return Renderer.Handler; } set { Renderer.Handler = value; } }

        public override Renderer Renderer
        {
            get
            {
                var r = base.Renderer;
                if (r.Handler.IsEmpty())
                    r.Handler = GetRender();
                return r;
            }
            set { base.Renderer = value; }
        }

        public virtual string GetRender()
        {
            if (Kind == ColumnKind.None) return "return '&nbsp;';";

            var sb0 = new StringBuilder();
            var sb = new StringBuilder();
            sb.Append("[");
            RenderBorders_b(sb0, sb);
            RenderIcon_b(sb0, sb, ShowOkIcon, ShowErrorIcon);
            RenderKind_b(sb0, sb, Kind);

            RenderArray_b(sb0, sb);

            RenderLink_b(sb0, sb);
            RenderValue(sb0, sb);
            RenderLink_e(sb0, sb);

            RenderArray_e(sb0, sb);

            RenderKind_e(sb0, sb, Kind);
            RenderIcon_e(sb0, sb, ShowOkIcon, ShowErrorIcon);
            RenderBorders_e(sb0, sb);
            sb.Append("].join('')");

            sb.Append(";");
            var s = sb0 + "return " + sb;
            if (s == "return [value || '&nbsp;'].join('');") s = null;
            return s;
        }

        internal protected void RenderBorders_b(StringBuilder sb0, StringBuilder sb)
        {
            if (BorderRight == ColumnBorderKind.None) return;
            throw new NotImplementedException();
            //sb.AppendLine(@"'<div class=""kl-col-rbrd" + (int)BorderRight + @""">',");
        }
        internal protected void RenderBorders_e(StringBuilder sb0, StringBuilder sb)
        {
            //if (BorderRight == ColumnBorderKind.None) return;
            //sb.Append(@", '</div>'");
        }

        internal protected void RenderIcon_b(StringBuilder sb0, StringBuilder sb, bool showOk, bool showError)
        {
            if (!showOk && !showError) return;
            sb0.Append("var ok = record.data[this.dataIndex+'_ok'];");
            sb.Append(@"'<div class=""cell-icon-text ',(!ok ? '");
            sb.Append(showError ? "icon-error-16" : null);
            sb.Append("' : ok ? '");
            sb.Append(showOk ? "icon-ok-16" : null);
            sb.Append(@"' : ''),'"">',");
        }
        internal protected void RenderIcon_e(StringBuilder sb0, StringBuilder sb, bool showOk, bool showError)
        {
            if (showOk || showError)
            {
                sb.Append(",'</div>'");
            }
        }

        internal protected void RenderKind_b(StringBuilder sb0, StringBuilder sb, ColumnKind kind)
        {
            sb.Append(
                kind == ColumnKind.Main ? "'<b>'," :
                kind == ColumnKind.Secondary ? @"'<span class=""kl-col-sec"">'," :
                kind == ColumnKind.Utility ? @"'<span class=""kl-col-util"">'," :
                null
            );
        }
        internal protected void RenderKind_e(StringBuilder sb0, StringBuilder sb, ColumnKind kind)
        {
            sb.Append(
                kind == ColumnKind.Main ? ",'</b>'" :
                kind == ColumnKind.Secondary ? @",'</span>'" :
                kind == ColumnKind.Utility ? @",'</span>'" :
                null
            );
        }

        internal protected void RenderArray_b(StringBuilder sb0, StringBuilder sb)
        {
            if (!IsArray)
            {
                if (GetValue.IsNotEmpty())
                    sb0.AppendFormat("value = " + GetValue + ";");
                return;
            }

            sb.AppendLine(
@"(function(){
if (!value) return '';
var buf = [];
var ar = value;
for(var i = 0, len = ar.length; i < len; ++i) {
value = ar[i];");
            if (GetValue.IsNotEmpty())
                sb.AppendLine("value = " + GetValue + ";");
            sb.Append(@"buf.push('<div>',");
        }
        internal protected void RenderArray_e(StringBuilder sb0, StringBuilder sb)
        {
            if (!IsArray) return;
            sb.Append(@", '</div>');} return buf.join(''); })()");
        }

        internal protected void RenderLink_b(StringBuilder sb0, StringBuilder sb)
        {
            //var link = Link;
            //if (link.LID.IsEmpty() && link.LIID.IsEmpty()) return;

            //if (link.LookupField.IsEmpty()) link.LookupField = DataIndex;
            //if (link.LookupField.IsEmpty()) { link.LookupField = null; return; }

            //if (link.KeyField.IsEmpty()) link.KeyField = DataIndex;
            //if (link.KeyField.IsEmpty()) { link.KeyField = null; return; }

            //var grid = ParentGrid as Grid;
            //ListLogic lgrid = null;
            //if (grid != null)
            //    lgrid = grid.Logic;

            //if (link.LID.IsEmpty()) link.LID = lgrid != null ? lgrid.Controller.LID : null;
            //if (link.LID.IsEmpty()) { link.LID = null; return; }
            //if (link.LIID.IsEmpty()) link.LIID = "Form";


            //var cols = ParentGrid.ColumnModel.Columns;
            //string idJson = null;
            //var i = 0;
            //foreach (var lookupName in link.LookupFields)
            //{
            //    if (idJson != null) idJson += ",";
            //    var lookup = "record.data['" + lookupName + @"']";
            //    string getValue = null;
            //    if (lookupName == Name)
            //    {
            //        if (IsArray)
            //            lookup = "value";
            //        else
            //            getValue = GetValue;
            //    }
            //    else
            //    {
            //        var idCol = cols.FirstOrDefault(a => a.DataIndex == lookupName);
            //        if (idCol != null && idCol is Column)
            //            getValue = ((Column)idCol).GetValue;
            //    }
            //    if (getValue != null)
            //        lookup = @"(function(value){return " + getValue + ";})(" + lookup + ")";
            //    idJson += (i < link.KeyFields.Length ? link.KeyFields[i] : lookupName) + @":\''+" + lookup + @"+'\'";
            //    i++;
            //}

            //string midJson = null;
            //if (link.MasterIDs != null)
            //{
            //    i = 0;
            //    foreach (var lmidName in link.LookupMasterIDs)
            //    {
            //        if (midJson != null) midJson += ",";

            //        var lookup = "record.data['" + lmidName + @"']";
            //        string getValue = null;
            //        if (lmidName == Name)
            //        {
            //            if (IsArray)
            //                lookup = "value";
            //            else
            //                getValue = GetValue;
            //        }
            //        else
            //        {
            //            var idCol = cols.FirstOrDefault(a => a.DataIndex == lmidName);
            //            if (idCol != null && idCol is Column)
            //                getValue = ((Column)idCol).GetValue;
            //        }
            //        if (getValue != null)
            //            lookup = @"(function(value){return " + getValue + ";})(" + lookup + ")";

            //        midJson += (i < link.MasterIDs.Length ? link.MasterIDs[i] : lmidName) + @":\'' + " + lookup + @"+'\'";
            //        i++;
            //    }
            //    if (midJson != null) midJson = ", mid:{" + midJson + "}";
            //}

            //sb.AppendFormat(
            //    @"!value ? '&nbsp;' : '<a href=""javascript:"" onclick=""KamLib.Logic.Form.editEntity({{lid:\'{0}\', liid:\'{1}\', id:{{{2}}}{3} }}, false, this);"">',",
            //    link.LID, link.LIID, idJson, midJson
            //);
        }
        internal protected void RenderLink_e(StringBuilder sb0, StringBuilder sb)
        {
            //if (Link.Active)
            //    sb.Append(",!value ? '' : '</a>'");
        }

        protected virtual void RenderValue(StringBuilder sb0, StringBuilder sb)
        {
            if (LookupStoreClientID.isfull())
            {
                sb0.Append("var r;");
                sb.AppendFormat(
                    @"((r={0}.getById(value))?r.get('{1}'):value)||'&nbsp;'",
                    LookupStoreClientID, LookupField ?? "n");
            }
            else
                sb.Append("value || '&nbsp;'");
        }

        #endregion


        #region IColumnEditorFactory Members

        public virtual Field NewEditor()
        {
            return new TextField();
        }

        #endregion
    }

    public class ListFilter : global::Ext.Net.ListFilter
    {

        [NotifyParentProperty(true)]
        public string StoreClientID { get; set; }

        protected internal new string StoreProxy
        {
            get
            {
                return !StoreClientID.IsEmpty()
                    ? StoreClientID : !StoreID.IsEmpty()
                    ? ControlUtils.FindControl(ParentGrid, StoreID).ClientID : "";
            }
        }

        protected internal new string LabelFieldProxy { get { return LabelField; } }

        public override ConfigOptionsCollection ConfigOptions
        {
            get
            {
                var list = base.ConfigOptions;
                //list.Remove("storeProxy");
                list.Add("storeProxy", new ConfigOption("storeProxy", new SerializationOptions("store", JsonMode.Raw), "", StoreProxy));
                list.Add("labelFieldProxy", new ConfigOption("labelFieldProxy", new SerializationOptions("labelField"), "text", LabelFieldProxy));
                return list;
            }
        }
    }


    public class NumberColumn : Column
    {

        [DefaultValue(Alignment.Right)]
        public override Alignment Align
        {
            get { return ViewState.Try("Align", Alignment.Right); }
            set { base.Align = value; }
        }

        [Category("3. NumberColumn")]
        [DefaultValue("0,000.00")]
        [Description("A formatting string as used by Ext.util.Format.number to format a numeric value for this Column (defaults to '0,000.00').")]
        public virtual string Format
        {
            get { return ViewState.Try("Format", "0,000.00"); }
            set { ViewState["Format"] = value; }
        }

        [DefaultValue(typeof(Unit), "60")]
        public override Unit Width
        {
            get { return ViewState.Try("Width", (Unit)60); }
            set { base.Width = value; }
        }

        protected override void RenderValue(StringBuilder sb0, StringBuilder sb)
        {
            var fmt = Format;
            sb.Append(fmt.IsEmpty()
                ? "value === null || value === undefined ? '&nbsp;' : value"
                : @"value === null || value === undefined ? '&nbsp;' : Ext.util.Format.number(value, """ + fmt + @""")"
            );
        }

        public override GridFilter NewSpecFilter()
        {
            return new NumericFilter { DataIndex = FilterName ?? DataIndex };
        }

        public override Field NewEditor()
        {
            return new NumberField { AllowBlank = AllowBlank };
        }
    }

    #endregion


    #region Boolean

    public class LabelColumn : Column, IRecordFieldInfo
    {
        public RecordFieldType FieldType { get { return RecordFieldType.Boolean; } }

        [DefaultValue(Alignment.Center)]
        public override Alignment Align
        {
            get { return ViewState.Try("Align", Alignment.Center); }
            set { base.Align = value; }
        }

        [DefaultValue(null)]
        public virtual string Label
        {
            get { return ViewState.Try("Label", (string)null); }
            set { ViewState["Label"] = value; }
        }

        protected override void RenderValue(StringBuilder sb0, StringBuilder sb)
        {
            var lbl = Label ?? Header;
            sb.Append("value ? '" + lbl + "': '&nbsp;'");
        }
    }

    public class YesNoColumn : global::Ext.Net.Column, IRecordFieldInfo, IColumnFilterFactory
    {
        public RecordFieldType FieldType { get { return RecordFieldType.Boolean; } }

        [DefaultValue(false)]
        [NotifyParentProperty(true)]
        public virtual bool Invert { get; set; }

        [NotifyParentProperty(true)]
        public virtual string Name { get { return DataIndex; } set { DataIndex = value; } }

        [DefaultValue(true)]
        [NotifyParentProperty(true)]
        public virtual bool ShowYes { get { return _ShowYes; } set { _ShowYes = value; } }
        protected bool _ShowYes = true;

        [DefaultValue(false)]
        [NotifyParentProperty(true)]
        public virtual bool ShowNo { get { return _ShowNo; } set { _ShowNo = value; } }
        protected bool _ShowNo;

        [DefaultValue(typeof(Unit), "60")]
        public override Unit Width
        {
            get { return ViewState.Try("Width", (Unit)60); }
            set { base.Width = value; }
        }

        private bool _Filterable = true;
        [NotifyParentProperty(true)]
        public bool Filterable { get { return _Filterable; } set { _Filterable = value; } }

        [NotifyParentProperty(true)]
        public virtual string FilterName { get; set; }

        public virtual GridFilter NewFilter()
        {
            return Filterable ? new BooleanFilter { DataIndex = FilterName ?? DataIndex } : null;
        }


        public override Renderer Renderer
        {
            get
            {
                var r = base.Renderer;
                if (r.Handler.IsEmpty())
                    r.Handler = GetRender();
                return r;
            }
            set { base.Renderer = value; }
        }

        public virtual string GetRender()
        {
            if (!ShowYes && !ShowNo) return "&nbsp;";

            var sb = new StringBuilder("return ");

            sb.Append(@"'<div class=""cell-icon-16 icon-' + (value === 'Y' || value === 'y' || value === true ? '");
            if (ShowYes) sb.Append(Invert ? "error" : "check");
            sb.Append("' : '");
            if (ShowNo) sb.Append(Invert ? "check" : "error");
            sb.Append(@"') + '-16"">'+");
            RenderValue(sb);
            sb.Append("+'</div>';");

            return sb.ToString();
        }

        protected virtual void RenderValue(StringBuilder sb)
        {
            sb.Append("'&nbsp;'");
        }
    }

    #endregion


    #region DateTime

    public class DateColumn : Column, IRecordFieldInfo
    {
        public RecordFieldType FieldType { get { return RecordFieldType.Date; } }

        [DefaultValue(Alignment.Center)]
        public override Alignment Align
        {
            get { return ViewState.Try("Align", Alignment.Center); }
            set { base.Align = value; }
        }

        [DefaultValue(typeof(Unit), "95")]
        public override Unit Width
        {
            get { return ViewState.Try("Width", (Unit)95); }
            set { base.Width = value; }
        }

        [DefaultValue("d/m/Y")]
        [NotifyParentProperty(true)]
        public virtual string DateFormat { get { return ViewState.Try("DateFormat", "d/m/Y"); } set { ViewState["DateFormat"] = value; } }

        [DefaultValue(ColumnKind.Normal)]
        [NotifyParentProperty(true)]
        public virtual ColumnKind DateKind { get { return ViewState.Try("DateKind", ColumnKind.Normal); } set { ViewState["DateKind"] = value; } }

        [DefaultValue("H:i:s")]
        [NotifyParentProperty(true)]
        public virtual string TimeFormat { get { return ViewState.Try("TimeFormat", "H:i:s"); } set { ViewState["TimeFormat"] = value; } }

        [DefaultValue(ColumnKind.None)]
        [NotifyParentProperty(true)]
        public virtual ColumnKind TimeKind { get { return ViewState.Try("TimeKind", ColumnKind.None); } set { ViewState["TimeKind"] = value; } }

        public override GridFilter NewSpecFilter()
        {
            return new DateFilter { DataIndex = FilterName ?? DataIndex };
        }

        protected override void RenderValue(StringBuilder sb0, StringBuilder sb)
        {
            var dateKind = DateKind;
            var timeKind = TimeKind;

            if (dateKind == timeKind)
            {
                RenderKind_b(sb0, sb, dateKind);
                sb.Append("Ext.util.Format.date(value, '" + DateFormat + " " + TimeFormat + "')");
                RenderKind_e(sb0, sb, dateKind);
            }
            else
            {
                if (dateKind != ColumnKind.None)
                {
                    RenderKind_b(sb0, sb, DateKind);
                    sb.Append("Ext.util.Format.date(value, '" + DateFormat + "')");
                    RenderKind_e(sb0, sb, DateKind);
                }
                if (dateKind != ColumnKind.None && timeKind != ColumnKind.None)
                {
                    sb.Append("+' '+");
                }
                if (timeKind != ColumnKind.None)
                {
                    RenderKind_b(sb0, sb, timeKind);
                    sb.Append("Ext.util.Format.date(value, '" + TimeFormat + "')");
                    RenderKind_e(sb0, sb, timeKind);
                }
            }
        }

    }

    public class DateTimeColumn : DateColumn
    {
        [DefaultValue(typeof(Unit), "155")]
        public override Unit Width
        {
            get { return ViewState.Try("Width", (Unit)155); }
            set { base.Width = value; }
        }

        [DefaultValue(ColumnKind.Normal)]
        public override ColumnKind TimeKind { get { return ViewState.Try("TimeKind", ColumnKind.Normal); } set { base.TimeKind = value; } }
    }

    public class DateSTimeColumn : DateColumn
    {
        [DefaultValue(typeof(Unit), "130")]
        public override Unit Width
        {
            get { return ViewState.Try("Width", (Unit)130); }
            set { base.Width = value; }
        }

        [DefaultValue("H:i")]
        public override string TimeFormat { get { return ViewState.Try("TimeFormat", "H:i"); } set { base.TimeFormat = value; } }

        [DefaultValue(ColumnKind.Normal)]
        public override ColumnKind TimeKind { get { return ViewState.Try("TimeKind", ColumnKind.Normal); } set { base.TimeKind = value; } }
    }

    public class STimeColumn : DateSTimeColumn
    {
        [DefaultValue(typeof(Unit), "60")]
        public override Unit Width
        {
            get { return ViewState.Try("Width", (Unit)60); }
            set { base.Width = value; }
        }

        [DefaultValue(ColumnKind.None)]
        public override ColumnKind DateKind { get { return ColumnKind.None; } }

        #region IColumnEditorFactory Members

        public override Field NewEditor()
        {
            return new TimeField { AllowBlank = AllowBlank };
        }

        #endregion
    }

    #endregion


    #region Numbers

    public class IntColumn : NumberColumn, IRecordFieldInfo
    {
        public RecordFieldType FieldType { get { return RecordFieldType.Int; } }

        [DefaultValue("0,000")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000"); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new IntField { AllowBlank = AllowBlank };
        }
    }

    public class NumColumn : NumberColumn, IRecordFieldInfo
    {
        public RecordFieldType FieldType { get { return RecordFieldType.Float; } }

        [DefaultValue(".")]
        public override string Format
        {
            get { return ViewState.Try("Format", "."); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new IntField { AllowBlank = AllowBlank };
        }
    }

    #region FloatColumn

    public class FloatColumn : NumberColumn, IRecordFieldInfo
    {
        public RecordFieldType FieldType { get { return RecordFieldType.Float; } }

        [DefaultValue((string)null)]
        public override string Format
        {
            get { return ViewState.Try("Format", (string)null); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new FloatField { AllowBlank = AllowBlank };
        }
    }

    public class Float1Column : FloatColumn
    {
        [DefaultValue("0,000.0")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000.0"); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new Float1Field { AllowBlank = AllowBlank };
        }
    }

    public class Float2Column : FloatColumn
    {
        [DefaultValue("0,000.00")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000.00"); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new Float2Field { AllowBlank = AllowBlank };
        }
    }

    public class Float3Column : FloatColumn
    {
        [DefaultValue("0,000.000")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000.000"); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new Float3Field { AllowBlank = AllowBlank };
        }
    }

    public class Float4Column : FloatColumn
    {
        [DefaultValue("0,000.0000")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000.0000"); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new Float4Field { AllowBlank = AllowBlank };
        }
    }

    public class Float5Column : FloatColumn
    {
        [DefaultValue("0,000.00000")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000.00000"); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new Float5Field { AllowBlank = AllowBlank };
        }
    }

    public class Float6Column : FloatColumn
    {
        [DefaultValue("0,000.000000")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000.000000"); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new Float6Field { AllowBlank = AllowBlank };
        }
    }

    public class Float7Column : FloatColumn
    {
        [DefaultValue("0,000.0000000")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000.0000000"); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new Float7Field { AllowBlank = AllowBlank };
        }
    }

    public class Float8Column : FloatColumn
    {
        [DefaultValue("0,000.00000000")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000.00000000"); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new Float8Field { AllowBlank = AllowBlank };
        }
    }

    public class Float9Column : FloatColumn
    {
        [DefaultValue("0,000.000000000")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000.000000000"); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new Float9Field { AllowBlank = AllowBlank };
        }
    }

    public class Float10Column : FloatColumn
    {
        [DefaultValue("0,000.0000000000")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000.0000000000"); }
            set { base.Format = value; }
        }

        public override Field NewEditor()
        {
            return new Float10Field { AllowBlank = AllowBlank };
        }
    }

    #endregion

    #region PercColumn

    public class PercColumn : NumberColumn
    {
        public override Alignment Align
        {
            get { return ViewState.Try("Align", ShowProgress ? Alignment.Center : Alignment.Right); }
            set { base.Align = value; }
        }

        [DefaultValue(".%")]
        public override string Format
        {
            get { return ViewState.Try("Format", ".%"); }
            set { base.Format = value; }
        }

        [Category("3. PercColumn")]
        [DefaultValue(true)]
        public virtual bool ShowProgress
        {
            get { return ViewState.Try("ShowProgress", true); }
            set { ViewState["ShowProgress"] = value; }
        }

        protected override void RenderValue(StringBuilder sb0, StringBuilder sb)
        {
            var sb1 = new StringBuilder();
            base.RenderValue(sb0, sb1);
            sb0.Append("if (value === null || value === undefined) return '';");
            sb0.Append("var w = this.width-10;");
            sb0.Append("var vw = 0.01 * w * value;");
            sb0.Append("var v = " + sb1 + ";");
            sb.Append(
@"'<div class=""x-progress-wrap"" style=""height:18px;width:'+w+'px""><div class=""x-progress-inner"">" +
    @"<div class=""x-progress-bar"" style=""width:' + vw + 'px"">" +
        @"<div class=""x-progress-text"" style=""z-index:99;width:'+(vw>9?vw-9:0)+'px"">" +
            @"<div style=""width:'+w+'px"">'+v+'</div>" +
        @"</div>" +
    @"</div>" +
    @"<div class=""x-progress-text x-progress-text-back""><div style=""width:' + w + 'px"">' + v + '</div></div>" +
@"</div></div>'"
            );
        }

        public override Field NewEditor()
        {
            return new PercField { AllowBlank = AllowBlank };
        }
    }
    public class Perc1Column : PercColumn
    {
        [DefaultValue("0,000.0%")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000.0%"); }
            set { base.Format = value; }
        }
    }

    public class Perc2Column : PercColumn
    {
        [DefaultValue("0,000.00%")]
        public override string Format
        {
            get { return ViewState.Try("Format", "0,000.00%"); }
            set { base.Format = value; }
        }
    }

    #endregion


    #endregion


    #region ComboBox

    public class SelectColumn : Column
    {
        [NotifyParentProperty(true)]
        public string StoreClientID { get; set; }

        private string _DisplayField = "n";
        [DefaultValue("n")]
        [NotifyParentProperty(true)]
        public string DisplayField { get { return _DisplayField; } set { _DisplayField = value; } }

        protected override void RenderValue(StringBuilder sb0, StringBuilder sb)
        {
            if (StoreClientID.IsEmpty())
                sb.Append("value || '&nbsp;'");
            else
            {
                sb.Append("(function(){var r=" + StoreClientID + ".getById(value);");
                sb.Append("return(r?r.data." + DisplayField + ":null)||'&nbsp;';})()");
            }
        }

        public override Field NewEditor()
        {
            return new SelectBox
            {
                AllowBlank = AllowBlank,
                StoreClientID = StoreClientID,
                DisplayField = DisplayField,
            };
        }
    }

    #endregion
}
